package io.github.talelin.latticy.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.github.talelin.autoconfigure.exception.NotFoundException;
import io.github.talelin.latticy.dto.wxUser.WxUserDTO;
import io.github.talelin.latticy.dto.wxUser.WxUserUpdateDTO;
import io.github.talelin.latticy.mapper.AddressMapper;
import io.github.talelin.latticy.mapper.WxUserMapper;
import io.github.talelin.latticy.model.AddressDO;
import io.github.talelin.latticy.model.WxUserDO;
import io.github.talelin.latticy.model.WxUserDetailDO;
import io.github.talelin.latticy.service.WxUserService;
import io.github.talelin.latticy.util.AesUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author generator@lms
 * @since 2021-04-20
 */
@Service
public class WxUserServiceImpl extends ServiceImpl<WxUserMapper, WxUserDO> implements WxUserService {

    @Value("${wx.code2session}")
    private String code2SessionUrl;
    @Value("${wx.appid}")
    private String appid;
    @Value("${wx.secret}")
    private String secret;

    @Autowired
    private AddressMapper addressMapper;

    @Override
    public WxUserDetailDO getDetail(Integer id) {
        WxUserDO wxUser = this.getById(id);
        if (wxUser == null) {
            throw new NotFoundException(20000);
        }
        QueryWrapper<AddressDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("uid", id);
        List<AddressDO> addressDOS = addressMapper.selectList(queryWrapper);

        List<String> addresses = new ArrayList<>();

        addressDOS.forEach(addressDO -> addresses.add(addressDO.getContent()));
        WxUserDetailDO userDetail = new WxUserDetailDO();

        userDetail.setAddresses(addresses);

        BeanUtils.copyProperties(wxUser, userDetail);
        return userDetail;
    }

    @Override
    public WxUserDO login(WxUserDTO dto) {
        String openId = getOpenId(dto.getCode());
        WxUserDO wxUser = new WxUserDO();
        wxUser.setUsername(dto.getNickname())
                .setAvatar(dto.getAvatarUrl())
                .setOpenid(openId)
                .setNativePlace(dto.getNativePlace());
        WxUserDO wxUserDO = getBaseMapper().selectOne(new QueryWrapper<WxUserDO>().eq("openid", wxUser.getOpenid()));
        if (wxUserDO == null) {
            getBaseMapper().insert(wxUser);
            wxUserDO = getBaseMapper().selectOne(new QueryWrapper<WxUserDO>().eq("openid", wxUser.getOpenid()));
        }
        return wxUserDO;
    }

    @Override
    public void updateInfo(WxUserUpdateDTO dto) {
        WxUserDO wxUser = new WxUserDO();
        BeanUtils.copyProperties(dto, wxUser);
        getBaseMapper().update(wxUser, new QueryWrapper<WxUserDO>().eq("id", wxUser.getId()));
    }

    private JSONObject decodeWxInfo(String code, String encryptedData, String iv) {
        String sessionKey = getSessionKey(code);

        if (encryptedData == null && iv == null && sessionKey == null) {
            throw new NotFoundException(55551, "微信用户信息 参数不完整！");
        }

        String decrypt = null;
        //解密
        try {
            decrypt = AesUtils.decryptWeChatRunInfo(sessionKey, encryptedData, iv);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (decrypt == null) {
            throw new NotFoundException(55555, "微信用户信息解密失败！");
        }

        return JSON.parseObject(decrypt);
    }

    private String getSessionKey(String code) {
        String url = MessageFormat.format(this.code2SessionUrl, this.appid, this.secret, code);
        RestTemplate restTemplate = new RestTemplate();
        String sessionText = restTemplate.getForObject(url, String.class);
        return JSON.parseObject(sessionText).getString("session_key");
    }

    private String getOpenId(String code) {
        String url = MessageFormat.format(this.code2SessionUrl, this.appid, this.secret, code);
        RestTemplate restTemplate = new RestTemplate();
        String sessionText = restTemplate.getForObject(url, String.class);
        return JSON.parseObject(sessionText).getString("openid");
    }
}
